
class_name SceneUnitManage
extends Node2D




## 排序信号，用于通知 UI 刷新
signal sort_signal
## 回合结算信号，用于通知 UI 刷新
signal round_settlement_signal

## 回合数
var round_number: int = 0
## 下标
var pointer: int = 0
## 当前 unit
var current_unit: Unit = null
## 行动列表
var action_unit_list: Array[Unit] = []
## 墓地
var cemetery: Array[Unit] = []




func _ready() -> void:
	# 设置随机数种子
	randomize()




## 开始
func start() -> void:
	action_unit_list = []
	var childs: Array[Node] = get_children()
	
	for unit in childs:
		action_unit_list.append(unit)
		_connect_unit(unit)
	
	settlement()
	cycle()




## 停止游戏
## TODO
func stop() -> void:
	pass




## 循环
func cycle() -> void:
	var next_unit: Unit = get_next_unit()
	unit_action_start(next_unit)




## 添加 unit
func add_unit(_unit: Unit) -> void:
	add_child(_unit)




## 删除 unit
func remove_unit(_unit: Unit) -> void:
	action_unit_list.erase(_unit)
	# 如果要删除的 unit 不在待机状态（也就是还未行动）就要删除的同时把指针向前移一个位置
	if _unit.property.action_state != UnitProperty.ACTION_STATE.NONE:
		pointer -= 1
	
	# 获取当前剩余的 unit 并检查它们的 camp
	# 只剩下一种时，就结算
	# （需要进行迁移）
	var camps: PackedStringArray = []
	for unit in get_all_units():
		if camps.find(unit.controller.camp) == -1:
			camps.append(unit.controller.camp)
	
	if camps.size() == 1:
		get_parent().end(camps[0])




## 连接 unit 信号
func _connect_unit(_unit: Unit) -> void:
	_unit.attack_request_signal.connect(unit_attack_request)
	_unit.move_request_signal.connect(unit_move_request)
	
	_unit.action_end_siganl.connect(unit_action_end)
	_unit.show_scope_signal.connect(unit_show_scope)
	
	_unit.die_signal.connect(add_unit_to_cemetery)




## 断开 unit 信号
func _disconnect_unit(_unit: Unit) -> void:
	_unit.attack_request_signal.disconnect(unit_attack_request)
	_unit.move_request_signal.disconnect(unit_move_request)
	
	_unit.action_end_siganl.disconnect(unit_action_end)
	_unit.show_scope_signal.disconnect(unit_show_scope)
	
	_unit.die_signal.disconnect(add_unit_to_cemetery)




## 获取攻击范围
func get_unit_attack_scope(_unit: Unit, _position: Vector2 , _transform: bool = true) -> PackedVector2Array:
	var parent: Node = get_parent()
	
	var mode: CreateGrid.CREATE_GRID_MODE = CreateGrid.CREATE_GRID_MODE.CROSS
	var step: int = _unit.property.attack_length
	var ignore: Array = _unit.property.attack_ignore
	var offset: Vector2 = parent.map.local_to_map(_position)
	
	# 转换类型
	match _unit.property.attack_range_type:
		UnitProperty.ATTACK_RANGE_TYPE.CROSS:
			pass
		
		UnitProperty.ATTACK_RANGE_TYPE.RANGE:
			mode = CreateGrid.CREATE_GRID_MODE.RANGE
		
		UnitProperty.ATTACK_RANGE_TYPE.TILE_CROSS:
			mode = CreateGrid.CREATE_GRID_MODE.TILE_CROSS
		
		UnitProperty.ATTACK_RANGE_TYPE.TILE_RANGE:
			mode = CreateGrid.CREATE_GRID_MODE.TILE_RANGE
	
	# 获得范围
	var range: PackedVector2Array = GCreateGrid.create_grid(mode, step, ignore, offset)
	
	# 转换 position
	if _transform:
		for index in range(0, range.size()):
			range[index] = parent.map.map_to_local(range[index])
	
	return range




## unit 攻击请求
func unit_attack_request(_unit: Unit) -> void:
	var range: PackedVector2Array = get_unit_attack_scope(_unit, _unit.position)
	
	# 显示
	get_parent().select_manage.show_range(
		range,
		SceneSelectManage.SelectMangerMode.ATTACK,
		call_attack_settlement, {
			"unit": _unit
		}
	)




## unit 移动请求
func unit_move_request(_unit: Unit) -> void:
	var cost_list: Dictionary = get_parent().map.get_unit_move_range(_unit, true)
	var gumr: Array = cost_list.keys()
	
	# 删掉与其它 unit 重叠的部分
	for unit in get_all_units():
		gumr.erase(unit.position)
	
	get_parent().select_manage.show_range(
		gumr,
		SceneSelectManage.SelectMangerMode.MOVE,
		get_parent().map.call_pathfinding, {
			"unit": _unit,
			"cost_list": cost_list
		}
	)




## 回调 attack 结算
## 这个会由 SelectManage 调用
## 玩家在使用 unit 攻击时需要挑选区域
## 选中区域后会调用此方法
func call_attack_settlement(_args: Dictionary) -> bool:
	var attacker: Unit = _args["unit"]
	var defender: Unit = null
	var target: Vector2 = _args["target_position"]
	
	# 判断位置上是否有单位
	# 有就进行攻击
	var units: Array[Unit] = get_position_units([target])
	
	if units.is_empty():
		return false
	
	defender = units[0]
	# 如果是空位就返回 false
	if defender == null:
		return false
	# 如果不为空，就进行战斗结算
	attack_settlement(attacker, defender)
	
	return true




## 攻击结算
## AI 因为攻击距离是自己算好的，所以不需要区域来选择，就可以直接调用这个方法
func attack_settlement(_attacker: Unit, _defender: Unit) -> void:
	await _attacker.action.attack_conduct(_defender)




## 显示 unit 的范围（移动范围 + 攻击范围）
## 点击单位时会调用
## 点击在行动的单位不会调用
func unit_show_scope(_unit: Unit) -> void:
	var gumr: Array = get_parent().map.get_unit_move_range(_unit, true).keys()
	
	# 删掉与其它 unit 重叠的部分
	for unit in get_all_units():
		gumr.erase(unit.position)
	
	# 生成攻击范围
	var guass: Dictionary = {}
	for item in gumr:
		for guas in get_unit_attack_scope(_unit, item):
			if not guass.has(guas):
				guass[guas] = null
	
	# 删除移动与攻击的重叠部分
	# 遍历移动范围，因为攻击范围在移动范围的基础上
	for item in gumr:
		guass.erase(item)
	
	var gsm: SceneSelectManage = get_parent().select_manage
	var a = gsm.show_range(gumr, SceneSelectManage.SelectMangerMode.SHOW_MOVE)[0]
	var b = gsm.show_range(guass.keys(), SceneSelectManage.SelectMangerMode.SHOW_ATTACK)[0]
	gsm.merge_layer(gsm.get_layer_index(a), gsm.get_layer_index(b))




## 获取下一个行动的 unit
func get_next_unit() -> Unit:
	var unit: Unit = null
	
	# 判断是否结束
	if pointer >= action_unit_list.size():
		settlement()
		unit = action_unit_list[pointer]
		pointer += 1
		return unit
	
	unit = action_unit_list[pointer]
	pointer += 1
	
	return unit




## 结算这一回合
func settlement() -> void:
	action_unit_list = []
	var childs: Array[Node] = get_children()
	
	# 在排序之前，为了放置因为行动优先度一样导致的行动列表无变化
	# 需要先打乱行动顺序
	for index in range(0, childs.size()):
		var rand = randi() % childs.size()
		var rand_unit = childs[rand]
		childs[rand] = childs[index]
		childs[index] = rand_unit
	
	# 排序
	childs.sort_custom(func (_front: Unit , _behind: Unit) -> bool:
		# 判断优先度
		if _front.property.priority > _behind.property.priority:
			return true
		return false
	)
	
	action_unit_list.append_array(childs)
	
	# 重置状态
	for unit in action_unit_list:
		unit.settlement()
		unit.cycle(round_number)
	
	pointer = 0
	
	# 增加回合数
	round_number += 1
	
	# 向外传递信号
	# sort_signal 会让显示unit队列的ui刷新
	emit_signal("sort_signal", action_unit_list)
	# round_settlement_signal 会让显示信息的ui刷新
	emit_signal("round_settlement_signal", round_number)




## 调用 unit 行动开始行动
func unit_action_start(_unit: Unit) -> void:
	_unit.start_action()




## unit 行动结束调用,会调用下一个单位行动
func unit_action_end(_unit: Unit) -> void:
	cycle()




## 返回所有 unit
func get_all_units() -> Array[Unit]:
	var result: Array[Unit] = []
	result.append_array(get_children())
	
	return result




## 返回所有 unit 可以根据参数来获取指定阵营内的 unit
## 如果不指定，就返回所有 unit
func get_camp_units(_camp: String = "") -> Array[Unit]:
	var result: Array[Unit] = []
	
	if not _camp.is_empty():
		for unit in get_children():
			if unit.get_unit_camp() == _camp:
				result.append(unit)
	
	else:
		return get_all_units()
	
	return result




## 返回所有指定位置上的 unit
func get_position_units(_range: PackedVector2Array = []) -> Array[Unit]:
	var result: Array[Unit] = []
	var units: Array[Node] = get_children()
	var d: Dictionary = {}
	
	if not _range.is_empty():
		for r in _range:
			for u in units:
				if u.position == r:
					result.append(u)
					break
	
	return result




## 添加 unit 到 墓地
## unit 挂了就调用这个
func add_unit_to_cemetery(_unit: Unit) -> void:
	# 将 unit 从场景树中删除
	# 并放入 墓地 中
	cemetery.append(_unit)
	remove_child(_unit)
	remove_unit(_unit)
	
	# 调用 ui 删除 unit 项
	get_parent().ui.queue_plan.remove_unit(_unit)




## 指针点击反应
func pointer_callable(_pointer: ScenePointer) -> Unit:
	var units: Array[Unit] = get_position_units([_pointer.position])
	
	if units.is_empty():
		return null
	
	return units[0]




## 指针移动
func pointer_move(_pointer: ScenePointer) -> Unit:
	var units: Array[Unit] = get_position_units([_pointer.position])
	
	if units.is_empty():
		return null
	
	return units[0]
